package com.keba.lamp.complaint.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import com.keba.basic.context.ContextUtil;
import com.keba.basic.database.mybatis.conditions.Wraps;
import com.keba.basic.utils.ArgumentAssert;
import com.keba.basic.utils.BeanPlusUtil;
import com.keba.basic.utils.DateUtils;
import com.keba.basic.utils.StrPool;
import com.keba.lamp.base.entity.common.BaseDict;
import com.keba.lamp.base.service.common.BaseDictService;
import com.keba.lamp.common.constant.AppendixType;
import com.keba.lamp.complaint.entity.*;
import com.keba.lamp.complaint.enumeration.DocTemplateTypeEnum;
import com.keba.lamp.complaint.manager.*;
import com.keba.lamp.complaint.vo.result.DocTemplateUserResultVO;
import com.keba.lamp.complaint.vo.save.AreaVO;
import com.keba.lamp.file.entity.Appendix;
import com.keba.lamp.file.entity.File;
import com.keba.lamp.file.service.AppendixService;
import com.keba.lamp.file.service.FileService;
import com.keba.lamp.model.constant.EchoDictType;
import com.keba.lamp.model.vo.result.AppendixResultVO;
import com.keba.lamp.office.properties.WebOfficeProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.keba.lamp.complaint.service.DocTemplateService;
import com.keba.basic.base.service.impl.SuperServiceImpl;
import com.keba.lamp.complaint.vo.save.DocTemplateSaveVO;
import com.keba.lamp.complaint.vo.update.DocTemplateUpdateVO;
import com.keba.lamp.complaint.vo.result.DocTemplateResultVO;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 文书模版
 * </p>
 *
 * @author twg
 * @date 2025-07-09 15:45:42
 * @create [2025-07-09 15:45:42] [twg] [代码生成器生成]
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DocTemplateServiceImpl extends SuperServiceImpl<DocTemplateManager, Long, DocTemplate> implements DocTemplateService {

    private final DocTemplateAreaManager docTemplateAreaManager;
    private final FileService fileService;
    private final AppendixService appendixService;

    private final BaseDictService baseDictService;

    private final PlaintffManager plaintffManager;
    private final DefendantManager defendantManager;
    private final AgentManager agentManager;
    private final WebOfficeProperties officeProperties;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<DocTemplateResultVO> listByAreaId(Long areaId, Long caseId) {
        List<Long> docTemplateIds = docTemplateAreaManager.list(Wraps.<DocTemplateArea>lbQ().select(DocTemplateArea::getDocTemplateId)
                .eq(DocTemplateArea::getAreaId, areaId)).stream().map(DocTemplateArea::getDocTemplateId).collect(Collectors.toList());
        if (CollUtil.isEmpty(docTemplateIds)) {
            return Collections.emptyList();
        }
        List<DocTemplateResultVO> list = new ArrayList<>();
        List<DocTemplate> docTemplates = listByIds(docTemplateIds);
        for (DocTemplate docTemplate : docTemplates) {
            if (docTemplate.getDocTemplateType().equals("01")) {
                if (StrUtil.containsAny(docTemplate.getApplyParty(), StrPool.ZERO)) {
                    //原告
                    List<Plaintff> plaintffs = plaintffManager.list(Wraps.<Plaintff>lbQ().eq(Plaintff::getCaseId, caseId).eq(Plaintff::getType, docTemplate.getPartyType()));
                    plaintffs.stream().filter(o -> StrUtil.isNotBlank(o.getName())).forEach(o -> {
                        DocTemplateResultVO docTemplateResultVO = DocTemplateResultVO.builder().parentDocTemplateId(docTemplate.getId().toString()).caseUserId(o.getId()).applyParty("0").partyType(o.getType()).caseId(caseId).docTemplateType(docTemplate.getDocTemplateType()).name(StrUtil.format("{}-{}", o.getName(), docTemplate.getName())).build();
                        DocTemplate doc = buildDocFileId(Convert.toLong(docTemplateResultVO.getParentDocTemplateId()), docTemplateResultVO.getCaseId(), docTemplateResultVO.getCaseUserId(), docTemplateResultVO.getApplyParty(), docTemplateResultVO.getPartyType(), docTemplateResultVO.getDocTemplateType(), docTemplateResultVO.getName());
                        list.add(docTemplateResultVO.setId(doc.getId()).setEditStatus(doc.getEditStatus()).setAppId(officeProperties.getAppId()));
                    });
                }
                if (StrUtil.containsAny(docTemplate.getApplyParty(), StrPool.ONE)) {
                    List<Defendant> defendants = defendantManager.list(Wraps.<Defendant>lbQ().eq(Defendant::getCaseId, caseId).eq(Defendant::getType, docTemplate.getPartyType()));
                    defendants.stream().filter(o -> StrUtil.isNotBlank(o.getName())).forEach(o -> {
                        DocTemplateResultVO docTemplateResultVO = DocTemplateResultVO.builder().parentDocTemplateId(docTemplate.getId().toString()).caseUserId(o.getId()).applyParty("1").partyType(o.getType()).caseId(caseId).docTemplateType(docTemplate.getDocTemplateType()).name(StrUtil.format("{}-{}", o.getName(), docTemplate.getName())).build();
                        DocTemplate doc = buildDocFileId(Convert.toLong(docTemplateResultVO.getParentDocTemplateId()), docTemplateResultVO.getCaseId(), docTemplateResultVO.getCaseUserId(), docTemplateResultVO.getApplyParty(), docTemplateResultVO.getPartyType(), docTemplateResultVO.getDocTemplateType(), docTemplateResultVO.getName());
                        list.add(docTemplateResultVO.setId(doc.getId()).setEditStatus(doc.getEditStatus()).setAppId(officeProperties.getAppId()));
                    });
                }
            } else {
                DocTemplateResultVO docTemplateResultVO = DocTemplateResultVO.builder().parentDocTemplateId(docTemplate.getId().toString()).name(docTemplate.getName()).caseId(caseId).applyParty(docTemplate.getApplyParty()).partyType(docTemplate.getPartyType()).docTemplateType(docTemplate.getDocTemplateType()).build();
                DocTemplate doc = buildDocFileId(Convert.toLong(docTemplateResultVO.getParentDocTemplateId()), docTemplateResultVO.getCaseId(), docTemplateResultVO.getCaseUserId(), docTemplateResultVO.getApplyParty(), docTemplateResultVO.getPartyType(), docTemplateResultVO.getDocTemplateType(), docTemplateResultVO.getName());
                list.add(docTemplateResultVO.setId(doc.getId()).setEditStatus(doc.getEditStatus()).setAppId(officeProperties.getAppId()));
            }
        }
        return list;
    }

    /**
     * 构建案件模版关系表
     *
     * @param docId           模版id
     * @param caseId          案件id
     * @param caseUserId      案件用户
     * @param applyParty
     * @param partyType
     * @param docTemplateType
     * @return
     */
    private DocTemplate buildDocFileId(Long docId, Long caseId, Long caseUserId, String applyParty, Integer partyType, String docTemplateType, String docName) {
        DocTemplate docTemplate = superManager.getOne(Wraps.<DocTemplate>lbQ().eq(DocTemplate::getParentDocTemplateId, docId).eq(DocTemplate::getDocTemplateType, docTemplateType)
                .eq(Objects.nonNull(caseUserId), DocTemplate::getCaseUserId, caseUserId).eq(DocTemplate::getCaseId, caseId).eq(DocTemplate::getApplyParty, applyParty).eq(DocTemplate::getPartyType, partyType));
        if (Objects.nonNull(docTemplate)) {
            return docTemplate;
        }
        docTemplate = getById(docId);
        DocTemplate template = new DocTemplate().setCode(docTemplate.getCode() + "1").setName(docName).setCaseId(caseId).setCaseUserId(caseUserId).setApplyParty(applyParty)
                .setPartyType(partyType).setVersion(1).setSize(docTemplate.getSize()).setDocType(docTemplate.getDocType()).setDocTemplateType(docTemplate.getDocTemplateType())
                .setEditStatus(Boolean.FALSE).setParentDocTemplateId(Convert.toStr(docId));
        superManager.save(template);
        //保存模版文件的路径
        //获取模版的文件保存信息
        AppendixResultVO appendixResultVO = appendixService.getByBiz(docId, AppendixType.Complaint.COMPLAINT__OFFICE__FILE);
        if (appendixResultVO == null) {
            return template;
        }
        //复制一份
        File oldFile = fileService.getById(appendixResultVO.getId());
        File file = BeanPlusUtil.toBean(oldFile, File.class);
        file.setBizType(DocTemplateTypeEnum.getByCode(docTemplateType).getDesc()).setId(null);
        file.setCreatedTime(null);
        file.setUpdatedTime(null);
        fileService.getSuperManager().save(file);
        Appendix appendix = BeanPlusUtil.toBean(appendixResultVO, Appendix.class);
        appendix.setBizType(file.getBizType()).setBizId(template.getId()).setTenantId(ContextUtil.getTenantId());
        appendix.setId(file.getId());
        appendixService.save(appendix);
        return template;
    }

    @Override
    public DocTemplateUserResultVO getDocTemplateValue(Long docId) {
        DocTemplateUserResultVO docTemplateUserResultVO = DocTemplateUserResultVO.builder().build();
        DocTemplate docTemplate = getById(docId);
        if (Objects.isNull(docTemplate) || Objects.isNull(docTemplate.getCaseId())) {
            return docTemplateUserResultVO;
        }
        if (docTemplate.getDocTemplateType().equals("01")) {
            StrUtil.split(docTemplate.getApplyParty(), StrUtil.C_COMMA).forEach(o -> {
                if (o.equals(StrPool.ZERO)) {
                    buildPlaintiff(docTemplate, docTemplateUserResultVO);
                    buildPlaintiffAgent(docTemplate, docTemplateUserResultVO);
                } else {
                    buildDefendant(docTemplate, docTemplateUserResultVO);
                    buildDefendantAgent(docTemplate, docTemplateUserResultVO);
                }
            });

        }

        return docTemplateUserResultVO;

    }


    @Override
    public List<Long> listComeFileByCaseIdAndBizType(Long caseId, String bizType) {
        List<DocTemplate> docTemplates = list(Wraps.<DocTemplate>lbQ().eq(DocTemplate::getCaseId, caseId).eq(DocTemplate::getDocTemplateType, DocTemplateTypeEnum.getByDesc(bizType).getCode()));
        if (CollUtil.isEmpty(docTemplates)) {
            return new ArrayList<>();
        }
        List<Appendix> appendixList = appendixService.list(Wraps.<Appendix>lbQ().in(Appendix::getBizId, docTemplates.stream().map(DocTemplate::getId).collect(Collectors.toList()))
                .eq(Appendix::getBizType, bizType)
        );
        return appendixList.stream().map(Appendix::getId).collect(Collectors.toList());
    }


    @Override
    public List<AppendixResultVO> listAppendixByCaseIdAndBizType(Long caseId, String bizType) {
        List<DocTemplate> docTemplates = list(Wraps.<DocTemplate>lbQ().eq(DocTemplate::getCaseId, caseId).eq(DocTemplate::getDocTemplateType, DocTemplateTypeEnum.getByDesc(bizType).getCode()));
        if (CollUtil.isEmpty(docTemplates)) {
            return new ArrayList<>();
        }
        List<Appendix> appendixList = appendixService.list(Wraps.<Appendix>lbQ().in(Appendix::getBizId, docTemplates.stream().map(DocTemplate::getId).collect(Collectors.toList()))
                .eq(Appendix::getBizType, bizType)
        );
        return BeanPlusUtil.toBeanList(appendixList, AppendixResultVO.class);
    }

    private void buildPlaintiffAgent(DocTemplate docTemplate, DocTemplateUserResultVO docTemplateUser) {
        Agent agent = agentManager.getOne(Wraps.<Agent>lbQ().eq(Agent::getType, 0).eq(Agent::getCaseId, docTemplate.getCaseId()));
        if (agent == null) {
            return;
        }
        BaseDict baseDict = baseDictService.getByParentKeyAndKey(EchoDictType.Global.NATION, agent.getNation());
        docTemplateUser.setPlaintiffAgentName(agent.getName()).setPlaintiffAgentMobile(agent.getMobile())
                .setPlaintiffAgentAddress(agent.getAddress())
                .setPlaintiffAgentBirthDate(DateUtils.format(agent.getBirthDate(), DatePattern.CHINESE_DATE_PATTERN))
                .setPlaintiffAgentNation(Objects.isNull(baseDict) ? "" : baseDict.getName())
                .setPlaintiffAgentSex(formateSex(agent.getIdCard()))
                .setPlaintiffAgentIdType(formateIdType(agent.getIdType()))
                .setPlaintiffAgentCountry(Convert.toInt(agent.getCountry(), 0).equals(0) ? "中国" : "其他");
    }

    private void buildDefendantAgent(DocTemplate docTemplate, DocTemplateUserResultVO docTemplateUser) {
        Agent agent = agentManager.getOne(Wraps.<Agent>lbQ().eq(Agent::getType, 1).eq(Agent::getCaseId, docTemplate.getCaseId()));
        if (agent == null) {
            return;
        }
        BaseDict baseDict = baseDictService.getByParentKeyAndKey(EchoDictType.Global.NATION, agent.getNation());
        docTemplateUser.setDefendantAgentName(agent.getName()).setDefendantAgentMobile(agent.getMobile())
                .setDefendantAgentAddress(agent.getAddress())
                .setDefendantAgentBirthDate(DateUtils.format(agent.getBirthDate(), DatePattern.CHINESE_DATE_PATTERN))
                .setDefendantAgentNation(Objects.isNull(baseDict) ? "" : baseDict.getName())
                .setDefendantAgentSex(formateSex(agent.getIdCard()))
                .setDefendantAgentIdType(formateIdType(agent.getIdType()))
                .setDefendantAgentCountry(Convert.toInt(agent.getCountry(), 0).equals(0) ? "中国" : "其他");
    }

    private void buildDefendant(DocTemplate docTemplate, DocTemplateUserResultVO docTemplateUser) {
        Defendant defendant = defendantManager.getById(docTemplate.getCaseUserId());
        BaseDict baseDict = baseDictService.getByParentKeyAndKey(EchoDictType.Global.NATION, defendant.getNation());
        docTemplateUser.setDefendantName(defendant.getName()).setDefendantMobile(defendant.getMobile())
                .setDefendantAddress(defendant.getAddress())
                .setDefendantBirthDate(DateUtils.format(defendant.getBirthDate(), DatePattern.CHINESE_DATE_PATTERN))
                .setDefendantNation(Objects.isNull(baseDict) ? "" : baseDict.getName())
                .setDefendantSex(formateSex(defendant.getIdCard()))
                .setDefendantIdType(formateIdType(defendant.getIdType()))
                .setDefendantCountry(Convert.toInt(defendant.getCountry(), 0).equals(0) ? "中国" : "其他");
    }

    private void buildPlaintiff(DocTemplate docTemplate, DocTemplateUserResultVO docTemplateUser) {
        Plaintff plaintff = plaintffManager.getById(docTemplate.getCaseUserId());
        docTemplateUser.setPlaintiffName(plaintff.getName()).setPlaintiffMobile(plaintff.getMobile())
                .setPlaintiffAddress(plaintff.getAddress())
                .setPlaintiffBirthDate(formateBirthDate(plaintff.getBirthDate()))
                .setPlaintiffNation(formateNation(plaintff.getNation()))
                .setPlaintiffSex(formateSex(plaintff.getIdCard()))
                .setPlaintiffIdType(formateIdType(plaintff.getIdType()))
                .setPlaintiffCountry(Convert.toInt(plaintff.getCountry(), 0).equals(0) ? "中国" : "其他");
    }

    private String formateNation(String nation) {
        BaseDict baseDict = baseDictService.getByParentKeyAndKey(EchoDictType.Global.NATION, nation);
        return Objects.isNull(baseDict) ? "" : baseDict.getName();
    }

    private String formateBirthDate(LocalDate birthDate) {
        if (Objects.isNull(birthDate)) {
            return "";
        }
        return DateUtils.format(birthDate, DatePattern.CHINESE_DATE_PATTERN);
    }

    private String formateIdType(Integer idType) {
        if (Objects.isNull(idType)) {
            return "";
        }
        return idType.equals(0) ? "身份证" : "社会信用代码证";
    }

    private String formateSex(String idCard) {
        if (StrUtil.isBlank(idCard)) {
            return "";
        }
        int sex = IdcardUtil.getGenderByIdCard(idCard);
        return 1 == sex ? "男" : "女";
    }

    @Override
    public <SaveVO> DocTemplate save(SaveVO saveVO) {
        DocTemplateSaveVO docTemplateSaveVO = (DocTemplateSaveVO) saveVO;
        List<AreaVO> areas = docTemplateSaveVO.getAreas().stream().filter(o -> !checkExists(o.getAreaId(), docTemplateSaveVO.getApplyParty(),
                docTemplateSaveVO.getPartyType(), docTemplateSaveVO.getDocTemplateType(), null)).collect(Collectors.toList());
        ArgumentAssert.isFalse(CollUtil.isEmpty(areas), "已存在相同的模板");
        docTemplateSaveVO.setCode(String.valueOf(superManager.getMaxCode() + 1));
        DocTemplate docTemplate = BeanUtil.toBean(docTemplateSaveVO, DocTemplate.class);
        getSuperManager().saveOrUpdate(docTemplate);
        saveAfter(docTemplateSaveVO, docTemplate);
        return docTemplate;
    }


    @Override
    public <SaveVO> void saveAfter(SaveVO saveVO, DocTemplate entity) {
        DocTemplateSaveVO docTemplateSaveVO = (DocTemplateSaveVO) saveVO;
        List<DocTemplateArea> docTemplateAreas = docTemplateSaveVO.getAreas().stream().map(o -> {
            return new DocTemplateArea().setDocTemplateId(entity.getId()).setCityName(o.getCityName()).setProvinceName(o.getProvinceName()).setAreaId(o.getAreaId());
        }).collect(Collectors.toList());
        docTemplateAreaManager.saveBatch(docTemplateAreas);
    }

    @Override
    public <UpdateVO> DocTemplate updateBefore(UpdateVO updateVO) {
        DocTemplateUpdateVO docTemplateUpdateVO = (DocTemplateUpdateVO) updateVO;
        List<AreaVO> areas = docTemplateUpdateVO.getAreas().stream().filter(o -> !checkExists(o.getAreaId(), docTemplateUpdateVO.getApplyParty(),
                docTemplateUpdateVO.getPartyType(), docTemplateUpdateVO.getDocTemplateType(), docTemplateUpdateVO.getId())).collect(Collectors.toList());
        ArgumentAssert.isFalse(CollUtil.isEmpty(areas), "已存在相同的模板");
        docTemplateAreaManager.remove(Wraps.<DocTemplateArea>lbQ().eq(DocTemplateArea::getDocTemplateId, docTemplateUpdateVO.getId()));
        return super.updateBefore(docTemplateUpdateVO.setAreas(areas));
    }

    @Override
    public <UpdateVO> void updateAfter(UpdateVO updateVO, DocTemplate entity) {
        DocTemplateUpdateVO docTemplateUpdateVO = (DocTemplateUpdateVO) updateVO;
        List<DocTemplateArea> docTemplateAreas = docTemplateUpdateVO.getAreas().stream().map(o -> {
            return new DocTemplateArea().setDocTemplateId(entity.getId()).setCityName(o.getCityName()).setProvinceName(o.getProvinceName()).setAreaId(o.getAreaId());
        }).collect(Collectors.toList());
        docTemplateAreaManager.saveBatch(docTemplateAreas);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeByIds(Collection<Long> idList) {
        List<DocTemplate> docTemplates = listByIds((List<Long>) idList);
        docTemplates.forEach(o -> {
            AppendixResultVO appendixResultVO = appendixService.getByBiz(o.getId(), DocTemplateTypeEnum.getByCode(o.getDocTemplateType()).getDesc());
            if (Objects.nonNull(appendixResultVO)) {
                fileService.removeByIds(Collections.singleton(appendixResultVO.getId()));
            }
            appendixService.removeByBizId(Collections.singleton(o.getId()), DocTemplateTypeEnum.getByCode(o.getDocTemplateType()).getDesc());
        });
        return super.removeByIds(idList);
    }

    private boolean checkExists(Long areaId, String applyParty, Integer partyType, String docTemplateType, Long id) {
        List<Long> docTemplateIds = docTemplateAreaManager.list(Wraps.<DocTemplateArea>lbQ().select(DocTemplateArea::getDocTemplateId)
                .eq(DocTemplateArea::getAreaId, areaId)).stream().map(DocTemplateArea::getDocTemplateId).collect(Collectors.toList());
        if (CollUtil.isEmpty(docTemplateIds)) {
            return false;
        }
        return this.superManager.exists(Wraps.<DocTemplate>lbQ()
                .ne(Objects.nonNull(id), DocTemplate::getId, id)
                .in(DocTemplate::getId, docTemplateIds)
                .like(DocTemplate::getApplyParty, applyParty)
                .eq(DocTemplate::getDocTemplateType, docTemplateType)
                .eq(DocTemplate::getPartyType, partyType));
    }
}


